package com.example.lte.service;

import com.example.lte.entity.OperationLogEntity;
import com.example.lte.po.ServerIpAddrInfo;
import com.example.lte.repo.OperationLogRepo;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;


/**
 * SystemLocalServiceImpl 包含异步处理服务和日志处理服务
 *
 *
 * Spring的"零配置"支持
 * 搜索Bean类
 * Spring提供如下几个Annotation来标注Spring Bean：
 * @Component: 标注一个普通的Spring Bean类
 * @Controller: 标注一个控制器组件类
 * @Service: 标注一个业务逻辑组件类
 * @Repository: 标注一个DAO组件类
 *
 * @author lzh
 * @date 2020/10/23 - 14:03
 */
@Service
public class SystemLocalServiceImpl implements ISystemLocalService {

    //Spring4.0增强的自动装配和精确装配
    //Spring提供了@Autowired注解来指定自动装配，
    // @Autowired可以修饰setter方法、普通方法、实例变量和构造器等。
    // 当使用@Autowired标注setter方法时，默认采用byType自动装配策略。
    // 在这种策略下，符合自动装配类型的候选Bean实例常常有多个，这个时候就可能引起异常，
    // 为了实现精确的自动装配，Spring提供了@Qualifier注解，通过使用@Qualifier，允许根据Bean的id来执行自动装配

    @Autowired
    private IAsyncService iAsyncService;

    //使用@Resource配置依赖
    //@Resource位于javax.annotation包下，是来自JavaEE规范的一个Annotation，
    // Spring直接借鉴了该Annotation，通过使用该Annotation为目标Bean指定协作者Bean。
    // 使用@Resource与<property.../>元素的ref属性有相同的效果。
    //@Resource不仅可以修饰setter方法，也可以直接修饰实例变量，
    // 如果使用@Resource修饰实例变量将会更加简单，
    // 此时Spring将会直接使用JavaEE规范的Field注入，此时连setter方法都可以不要

    @Resource
    private OperationLogRepo operationLogRepo;

    //@Resource 和 @Autowired，两者的区别，
    // @Resource 是 javax.annotation.Resource包下，是JavaEE支持的；
    // @Autowired 是org.springframework.beans.factory.annotation.Autowired 包下，是spring提供的，
    // 这会导致@Resource 的可扩展性优于 @Autowired，
    // 因为在导出一个项目时，使用 @Resource 注解，可以通过Java环境提供，
    // 而使用 @Autowired 注解的，需要额外引入spring包

    /**
     * 查询服务器IP和地址
     *
     * @return
     */
    @Override
    public ServerIpAddrInfo findIpAddr() throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException, ExecutionException, InterruptedException {

        Future<String> toolLu = iAsyncService.reqToolLuServerInfo();
        Future<String> pcOnline = iAsyncService.reqPcOnlineServerInfo();
        Future<String> chinaZ = iAsyncService.reqChinaZServerInfo();


        return ServerIpAddrInfo.builder()
                .chinaZBack(chinaZ.get())
                .pconlineBack(pcOnline.get())
                .toolLuBack(toolLu.get())
                .build();
    }

    /**
     * 页面查询日志
     *
     * @param account   账户
     * @param startDate 开始时间日期
     * @param endDate   结束时间日期
     * @return OperationLogEntity
     */
    @Override
    public Page<OperationLogEntity> getOperationLogPage(String account, Date startDate, Date endDate, Pageable pageable) {
        return operationLogRepo.findAll( (root,query,cb)->{
            List<Predicate> predicates = new ArrayList<>();
            //equal 示例
            if (!StringUtils.isEmpty(account)){
                predicates.add(cb.equal(root.get("account"),account));
            }
            //greaterThan 大于等于示例
            if (startDate!=null){
                predicates.add(cb.greaterThan(root.get("addTime"),startDate));
            }
            //lessThan 小于等于
            if (endDate!=null){
                predicates.add(cb.lessThan(root.get("addTime"),endDate));
            }

            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        },pageable);
    }


}
